<?php
/* 
 * Extensions to the standard PHP libraries.
 */

/**
 * Return whether all expected keys are present in array.
 * @param array array
 * @param array expected keys
 * @return bool result
 */
function all_keys_present($array, $expected_keys) {
    $actual_keys = array_keys($array);
    $intersect = array_intersect($actual_keys, $expected_keys);
    return count($intersect) == count($expected_keys);
}

/**
 * Convert a timestamp (in the past) to a friendly string, eg 3 minutes ago.
 * @param timestamp time to convert
 * @return string friendly time
 */
function friendly_time($time) {
    $SECOND = 1;
    $MINUTE = 60 * $SECOND;
    $HOUR = 60 * $MINUTE;
    $DAY = 24 * $HOUR;
    $MONTH = 30 * $DAY;

    $delta = time() - $time;

    if ($delta < 1 * $MINUTE) {
        return $delta == 1 ? "one second ago" : $delta . " seconds ago";
    }
    if ($delta < 2 * $MINUTE) {
        return "a minute ago";
    }
    if ($delta < 45 * $MINUTE) {
        return intval($delta / $MINUTE) . " minutes ago";
    }
    if ($delta < 90 * $MINUTE) {
        return "an hour ago";
    }
    if ($delta < 24 * $HOUR) {
        return intval($delta / $HOUR) . " hours ago";
    }
    if ($delta < 48 * $HOUR) {
        return "yesterday";
    }
    if ($delta < 30 * $DAY) {
        return intval($delta / $DAY) . " days ago";
    }
    if ($delta < 12 * $MONTH) {
        $days = $delta / $DAY;
        $months = intval(floor($days / 30));
        return $months <= 1 ? "one month ago" : $months . " months ago";
    } else {
        $days = $delta / $DAY;
        $years = intval(floor($days / 365));
        return $years <= 1 ? "one year ago" : $years . " years ago";
    }
}

/**
 * Syntactic sugar to allow the following:
 *
 * array_get(foo(bar), key)
 *
 * where foo() is a function that returns an array
 *
 * @param array
 * @param key
 * @return value
 */
function array_get($array, $key) {
    return $array[$key];
}

/**
 * Subtract a number of months from a timestamp.
 * @param timestamp starting month
 * @param int number of months to subtract
 * @return timestamp ending month
 */
function subtract_month($month, $amount=1) {
    return strtotime(date('Y-m', $month) . " -$amount month");
}

/**
 * For a given date return the number of months that have passed
 * since the year 0.
 * @param timestamp date
 * @return int number of months
 */
function months_since_year_0($date) {
    $year = intval(date('Y', $date));
    $month = intval(date('m', $date));
    return ($year * 12) + $month;
}

/**
 * Return a quantity with its correct plural/singular noun
 * eg 1 apple, 2 apples
 * @param int quantity to apply to noun, eg 1
 * @param string the singular form of the noun, eg apple
 * @param bool whether the quantity is returned with the noun, eg dogs
 * @param string the plural form of the noun, eg people
 * @return string quantity with correct noun
 */
function fnoun($quantity, $singular, $include_quantity=true, $plural=null) {
    $plural = $plural ? $plural : $singular . 's';
    $noun = ($quantity == 1 ? $singular : $plural);
    return $include_quantity ? $quantity . ' ' . $noun : $noun;
}

/**
 * Convert a pence currency value as a string to a formatted currency string
 * with currency sign and decimal place.
 * note: money_format() doesn't appear to display currency sign (even without
 * ! flag).
 * eg 300 => £3.00
 * @param string value of pence to convert, eg 300
 * @return string formatted currency string
 */
function to_money($amount_str) {
    return '&pound;' . money_format('%!.0n', $amount_str / 100);
}

/**
 * Return array of keys where the frequency of each key corresponds to its
 * probability weighting.
 *
 * array('a' => 2, 'b' => 1, c => 4)
 * outputs
 * array('a', 'a', 'b', 'c', 'c', 'c', 'c')
 * which can then be used with array_rand() to pick weighted key
 *
 * @param array array of key/weight pairs
 * @return array resultant array
 */
function weighted_key_array($weighted_keys) {
    foreach ($weighted_keys as $key => $weight) {
        for ($i = 0; $i < $weight; $i++) {
            $result[] = $key;
        }
    }
    return $result;
}

/**
 * Return random value from array.
 * @param array array
 * @return mixed array value
 */
function array_rand_value($array) {
    return $array[array_rand($array)];
}

?>
